package __goroutines

import (
	"fmt"
	"sync"
	"time"
)

func Demo() {
	routine()
	bufferChan()
	synchronization()
	selectChan()
}

func routine() {
	// 创建无缓存通道
	msg := make(chan string)
	// 开启协程
	go func() {
		fmt.Println("hello world")
		// 将值放入通道，阻塞
		msg <- "ping"
	}()
	// 从通道获取值，阻塞
	m := <-msg
	fmt.Println(m)
}

// 有缓冲通道
func bufferChan() {
	msg := make(chan string, 2)
	go func() {
		msg <- "1"
		msg <- "2"
		close(msg)
	}()
	//s1 := <-msg
	//s2 := <-msg
	//fmt.Println(s1, s2)

	// 如果用range就得关闭channel
	for i := range msg {
		fmt.Println(i)
	}
}

// 等待协程结束，也可以用 wait group
func synchronization() {
	done := make(chan bool)
	go worker(done)
	<-done
}

func worker(done chan bool) {
	fmt.Println("working on synchronization")
	time.Sleep(time.Second)
	fmt.Println("done")
	done <- true
}

// select的用法
func selectChan() {
	c1 := make(chan int)
	c2 := make(chan int)
	go func() {
		time.Sleep(1 * time.Second)
		c1 <- 1
		//close(c1)
	}()
	go func() {
		time.Sleep(2 * time.Second)
		c2 <- 2
		//close(c2)
	}()
	for i := 0; i < 2; i++ {
		select {
		case msg := <-c1:
			fmt.Println(msg)
		case msg := <-c2:
			fmt.Println(msg)
		}
	}
}

// 用于等待协程结束
func waitGroup() {
	// 创建变量
	var wg sync.WaitGroup
	for i := 0; i < 5; i++ {
		// 每启动一个协程就+1
		wg.Add(1)
		go func(x int) {
			// 每个协程结束前调用 Done()
			defer wg.Done()
			time.Sleep(time.Second)
			fmt.Println("x=", x)
		}(i)
	}
	// 主线程等待
	wg.Wait()

}
